<?php


namespace app\api\controller;


use app\common\controller\Api;
use app\common\controller\OperationLog;
use lib\Upload;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\exception\DbException;
use think\Hook;
use think\Request;

class File extends Api
{
    protected $noNeedLogin = [];
    protected $noNeedAuth = [];
    protected $noNeedToken = [];

    /**
     * 文件上传
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function upload()
    {
        // 定义日志参数
        $options = array(
            'title' => '上传附件',
            'method' => Request::instance()->action(),
            'request_method' => Request::instance()->method(),
            'open_url' => Request::instance()->url(),
            'oper_ip' => Request::instance()->ip(),
            'token' => Request::instance()->header('token')
        );
        $file = Request::instance()->file() ?? [];
        $param = Request::instance()->param() ?? [];
//        var_dump($file);
        $validRes = $this->validate($file + $param, 'File.uploads');
        if ($validRes !== true) {
            OperationLog::OperError($file + $param, $options, 'C', $validRes);
            $this->error('error', ['code' => 201, 'data' => $validRes]);
        }
        $attach = null;
        try {
            $upload = new Upload($file['file'], $param['tid']);
            $attach = $upload->upload();
            OperationLog::OperSuccess($file + $param, $options, 'C', '上传成功!');
            $this->success('success', ['code' => 200, 'data' => [
                'msg' => '上传成功!',
                'url' => $attach->uri
            ]]);
        } catch (Exception $e) {
            OperationLog::OperError($file + $param, $options, 'C', $e->getMessage());
            $this->error('error', ['code' => 202, 'data' => $e->getMessage()], 202);
        }
    }

    /**
     * 获取文件列表
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function lists()
    {
        // 定义日志参数
        $options = array(
            'title' => '获取附件',
            'method' => Request::instance()->action(),
            'request_method' => Request::instance()->method(),
            'open_url' => Request::instance()->url(),
            'oper_ip' => Request::instance()->ip(),
            'token' => Request::instance()->header('token')
        );
        $param = Request::instance()->param('where/a') ?? [];
        $page = Request::instance()->param('page') ?? '0,10';
        $where = self::build_params($param);
        $showFiled = [
            'id', 'tid', 'uri', 'filename', 'filesize', 'mimetype', 'upload_time'
        ];
        $fileLists = (new \app\api\model\File)
            ->field($showFiled)
            ->where($where)
            ->select();
        $pageFileLists = (new \app\api\model\File)
            ->field($showFiled)
            ->where($where)
            ->page($page)
            ->select();
        OperationLog::OperSuccess($param, $options, 'R', $pageFileLists);
        $this->success('success', ['code' => 200, 'data' => ['lists' => $pageFileLists, 'total' => count($fileLists)]]);
    }

    /**
     * 删除附件
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function del()
    {
        // 定义日志参数
        $options = array(
            'title' => '删除附件',
            'method' => Request::instance()->action(),
            'request_method' => Request::instance()->method(),
            'open_url' => Request::instance()->url(),
            'oper_ip' => Request::instance()->ip(),
            'token' => Request::instance()->header('token')
        );
        $param = Request::instance()->param() ?? [];
        $validRes = $this->validate($param, 'File.delete');
        if ($validRes !== true) {
            OperationLog::OperError($param, $options, 'D', $validRes);
            $this->error('error', ['code' => 201, 'data' => $validRes]);
        }
        Hook::add('upload_delete', function ($params) {
            $files = ROOT_PATH . '/public' . $params['uri'];
            if (is_file($files)) {
                @unlink($files);
                $params->delete(true);
            } else {
                $params->delete(true);
                Db::commit();
            }
        });
        Db::startTrans();
        try {
            foreach ($param['ids'] as $fileId) {
                $fileItem = \app\api\model\File::get(['id' => $fileId]);
                if (empty($fileItem)) {
                    if (count($param['ids']) == 1) {
                        OperationLog::OperError($fileId, $options, 'D', '文件不存在!');
                        $this->error('error', ['code' => 201, 'data' => '文件不存在!']);
                    } else {
                        continue;
                    }
                } else {
                    Hook::listen('upload_delete', $fileItem);
                    Db::commit();
                    OperationLog::OperSuccess($fileItem['id'], $options, 'D', '删除成功!');
                }
            }
            $this->success('success', ['code' => 200, 'data' => '删除成功!']);
        } catch (DataNotFoundException $e) {
            Db::rollback();
            OperationLog::OperError($param, $options, 'D', $e->getMessage());
            $this->error('error', ['code' => 202, 'data' => $e->getMessage()], '202');
        } catch
        (ModelNotFoundException $e) {
            Db::rollback();
            OperationLog::OperError($param, $options, 'D', $e->getMessage());
            $this->error('error', ['code' => 202, 'data' => $e->getMessage()], '202');
        } catch (DbException $e) {
            Db::rollback();
            OperationLog::OperError($param, $options, 'D', $e->getMessage());
            $this->error('error', ['code' => 202, 'data' => $e->getMessage()], '202');
        }
    }

    /**
     * 附件归类
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function classify()
    {
        // 定义日志参数
        $options = array(
            'title' => '附件归类',
            'method' => Request::instance()->action(),
            'request_method' => Request::instance()->method(),
            'open_url' => Request::instance()->url(),
            'oper_ip' => Request::instance()->ip(),
            'token' => Request::instance()->header('token')
        );
        $param = Request::instance()->param() ?? [];
        $validRes = $this->validate($param, 'File.classify');
        if ($validRes !== true) {
            OperationLog::OperError($param, $options, 'U', $validRes);
            $this->error('error', ['code' => 201, 'data' => $validRes]);
        }
        $checkFileTypeExist = \app\api\model\FileType::get(['id' => $param['tid']]);
        if (empty($checkFileTypeExist)) {
            OperationLog::OperError($param, $options, 'U', '附件类型不存在!');
            $this->error('error', ['code' => 201, 'data' => '附件类型不存在!']);
        } else {
            $fileLists = (new \app\api\model\File)
                ->where('id', 'in', $param['ids'])
                ->select();
            Db::startTrans();
            try {
                foreach ($fileLists as $fileItem) {
                    $fileItem->save([
                        'tid' => $param['tid']
                    ], ['id' => $fileItem['id']]);
                    Db::commit();
                    OperationLog::OperSuccess([
                        'fileId' => $fileItem['id'],
                        'tid' => $param['tid']
                    ], $options, 'U', '操作成功!');
                }
                $this->success('success', ['code' => 200, 'data' => '操作成功!']);
            } catch (Exception $e) {
                OperationLog::OperError($param, $options, 'u', $e->getMessage());
                $this->error('error', ['code' => 202, 'data' => $e->getMessage()], 202);
            }
        }
    }

    /**
     * 附件重命名
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function rename()
    {
        // 定义日志参数
        $options = array(
            'title' => '附件重命名',
            'method' => Request::instance()->action(),
            'request_method' => Request::instance()->method(),
            'open_url' => Request::instance()->url(),
            'oper_ip' => Request::instance()->ip(),
            'token' => Request::instance()->header('token')
        );
        $param = Request::instance()->param() ?? [];
        $validRes = $this->validate($param, 'File.rename');
        if ($validRes !== true) {
            OperationLog::OperError($param, $options, 'U', $validRes);
            $this->error('error', ['code' => 201, 'data' => $validRes]);
        }
        $checkFileExist = \app\api\model\File::get(['id' => $param['id']]);
        if (empty($checkFileExist)) {
            OperationLog::OperError($param, $options, 'U', '附件不存在!');
            $this->error('error', ['code' => 201, 'data' => '附件不存在!']);
        } else {
            Db::startTrans();
            try {
                $checkFileExist->save([
                    'filename' => $param['filename']
                ], ['id' => $param['id']]);
                Db::commit();
                OperationLog::OperSuccess($param, $options, 'U', '操作成功!');
                $this->success('success', ['code' => 200, 'data' => '操作成功!']);
            } catch (Exception $e) {
                Db::rollback();
                OperationLog::OperError($param, $options, 'U', $e->getMessage());
                $this->error('error', ['code' => 202, 'data' => $e->getMessage()], 202);
            }
        }
    }

    /**
     * 查看附件详情
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function detail()
    {
        // 定义日志参数
        $options = array(
            'title' => '查看附件详情',
            'method' => Request::instance()->action(),
            'request_method' => Request::instance()->method(),
            'open_url' => Request::instance()->url(),
            'oper_ip' => Request::instance()->ip(),
            'token' => Request::instance()->header('token')
        );
        $param = Request::instance()->param() ?? [];
        $validRes = $this->validate($param, 'File.detail');
        if ($validRes !== true) {
            OperationLog::OperError($param, $options, 'R', $validRes);
            $this->error('error', ['code' => 201, 'data' => $validRes]);
        }
        $field = [
            'id', 'filename', 'uri'
        ];
        $file = (new \app\api\model\File)
            ->field($field)
            ->where('id', '=', $param['id'])
            ->find();
        OperationLog::OperSuccess($param, $options, 'R',[$file]);
        $this->success('success', ['code' => 200, 'data' => $file]);
    }
}